#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <cstring>
#include <cerrno>
#include <errno.h>
using namespace std;

// pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
int ticket = 1000;
#define PTHREAD_NUM 5

class pthread_Data
{
   public:
   pthread_Data(const string& tn, pthread_mutex_t* tp):tname(tn), tpm(tp){} 

   string tname;
   pthread_mutex_t* tpm;
};


void* getticket(void* str)
{
    pthread_Data* td = (pthread_Data*) str;

    // 打印并进行取票
    while(1)
    {
        pthread_mutex_lock(td->tpm); // 加锁
        if (ticket > 0 )
        {     
        usleep(1000);
        ticket--;
        pthread_mutex_unlock(td->tpm); // 解锁
        // 为什么要将cout代码置出临界区？？
        // 对于多线程访问临界资源，我们需要考虑效率问题。将无关紧要的代码优化掉，提高临界区的颗粒，细密度。
        cout << td->tname.c_str() << " getticket : " << ticket << endl;
        }else
        {
            pthread_mutex_unlock(td->tpm);
            break;
        }
    }
    pthread_exit(nullptr);
}




int main()
{
    pthread_mutex_t pm;
    pthread_mutex_init(&pm, nullptr);

    pthread_t td[PTHREAD_NUM];
    for (int i = 0; i < PTHREAD_NUM; i++)
    {
       // 循环创建新线程
       string name = " thread ";
       name += to_string(i + 1);
       pthread_Data* pd = (pthread_Data*) new pthread_Data(name, &pm);
       pthread_create(td + i, nullptr, getticket, (void*)pd);
    }

    for (int i = 0 ; i < PTHREAD_NUM; i++)
    {
        pthread_join(td[i], nullptr);
    }
    
   pthread_mutex_destroy(&pm);
    return 0;
}







// __thread int tmp = 0;  // 定义一个全局变量，所以线程共享全局数据，及时修改也不会出现写实拷贝

// void *func(void* str)
// {
//     pthread_detach(pthread_self());
//     // int n = 5;
//     // int *data = new int[5];
//     // while (n--)
//     // {
//     //     cout << "new pthread play..., pid: " << getpid() << endl;
//     //     data[n] = n;    
//     //     sleep(1);
//     // }
    
//     // while (1)
//     // {
//     // cout << (char*)str << ":" << tmp << " &: " << &tmp << endl;
//     // tmp++;
//     // sleep(1);
//     // }
//     pthread_exit((void*)111);
//     // return (void*)data;
// }


// int main()
// {
//     pthread_t pt;
//     // for (int i = 0; i < 5; i++)
//     // {
//     //     pthread_create(pt + i, nullptr, func, (void* )"victor");
//     // }
//     pthread_create(&pt, nullptr, func, (void* )"new pthread ");
//     // sleep(3);

//     // pthread_cancel(pt); // 取消线程
//     // cout << "pthread_cancel get " << endl;

//     sleep(1);
//      int* ret = nullptr;
//      cout << "main thread " << endl;
//      int n = pthread_join(pt, (void**)&ret); // 等待线程退出
//      cout << "n : " << n << " error : " << strerror(n) << endl;  


//     // for (int i = 0; i < 5; i++)
//     // {
//     //     cout << ret[i]<< endl;
//     // }
//     // while (1)
//     // {
    
//     // cout << "main pthread " << ":" << tmp << " &: " << &tmp << endl;
//     // sleep(1);
//     // }
//     // while (1)
//     // {
//     //     cout << "main pthread play ...,  pid:" << getpid() << endl;
//     //     sleep(1);
//     // }
    
//     // cout << "main pthread play ...,  pid:" << getpid() << " ret :" << (long long )ret  << endl;
//     return 0;
// }


